﻿/************************************************************************
 * SMLib - State Model Library
 * Copyright (C) 2012-2013 Ali Khalili (khalili_DOT_ir_@SIGN_gmail_DOT_com)
 * **********************************************************************
 * This program is free software; you can redistribute it and/or modify it
 * under the terms of the GNU Lesser General Public License (LGPL) published 
 * by the Free Software Foundation; either version 2.1 of the License, or (at your
 * option) any later version. This program is distributed without any
 * warranty. See the GNU Lesser General Public License for more details. 
 * ***********************************************************************
 * File         :     SMLib\Interoperability\DOT\DotHelper_IA.cs
 * Description  :     DOT format helper for IAs
 * Change log   :     -1 Sep 2013:  Initial Version
 * To Do        :     
 ************************************************************************/
using System;
using System.Collections.Generic;
using SMLib.Automata.IA;
using SMLib.Utils;
using SMLib.Automata.Base;

namespace SMLib.Interoperability.DOT
{
    /// <summary>
    /// DOT Helper for interface automata
    /// </summary>
    public class DotHelper_IA :
        DotHelper<InterfaceAutomaton.IA_State,InterfaceAutomaton.IA_Step>
    {

        public static void WriteToDot(string path, InterfaceAutomaton mm)
        {
            SMLib.Interoperability.DOT.DotHelper_IA exporter = new SMLib.Interoperability.DOT.DotHelper_IA();
            (exporter as DotHelper<InterfaceAutomaton.IA_State,InterfaceAutomaton.IA_Step>).WriteToDot(path, mm);
        }

        /// <summary>
        /// Read a IA from dot file
        /// </summary>
        /// <param name="fileAddress">absolute path of the file</param>
        /// <returns>the interface automaton</returns>
        public static InterfaceAutomaton ReadFromDot(string fileAddress)
        {
            InterfaceAutomaton m = new InterfaceAutomaton();
            Alphabet inp = m.InputAlphabet;
            //m.inputAlphabet = new Alphabet();
            //m.outputAlphabet = new Alphabet();
            List<string> statesName = new List<string>();

            DotFormat dotReader = new DotFormat();
            string ilbl;
            foreach (DotFormat.DotTransition tr in dotReader.ReadDotFile(fileAddress))
            {
                ilbl = tr.Label;
                SMLib.Automata.IA.InterfaceAutomaton.IA_Step t = null;
                //* observable action
                if (tr.Label.StartsWith("!"))
                {
                    ilbl = ilbl.Substring(1);
                    t = new SMLib.Automata.IA.InterfaceAutomaton.IA_Step(new StringSymbol(ilbl), false);
                }
                //* controllable action
                else if (tr.Label.StartsWith("?"))
                {
                    ilbl = ilbl.Substring(1);
                    if (!inp.Contains(new StringSymbol(ilbl)))
                        inp.AddSymbol(new StringSymbol(ilbl));
                    t = new SMLib.Automata.IA.InterfaceAutomaton.IA_Step(new StringSymbol(ilbl), true);
                }
                //else if (tr.Label.StartsWith("!?"))
                //{
                //    throw new Exception("Not supported yet!");
                //}


                SMLib.Automata.IA.InterfaceAutomaton.IA_State srcNode = null, dstNode = null;
                int index = 0;
                foreach (string n in statesName)
                {
                    if (n.Equals(tr.Source))
                        srcNode = (SMLib.Automata.IA.InterfaceAutomaton.IA_State)m[index];

                    if (n.Equals(tr.Destination))
                        dstNode = (SMLib.Automata.IA.InterfaceAutomaton.IA_State)m[index];

                    if (dstNode != null && srcNode != null)
                        break;
                    index++;
                }

                if (srcNode == null)
                {
                    srcNode = new SMLib.Automata.IA.InterfaceAutomaton.IA_State(m.Size);
                    statesName.Add(tr.Source);

                    m.AddState(srcNode);

                    if (tr.Destination == tr.Source)
                        dstNode = srcNode;
                }

                if (dstNode == null)
                {
                    dstNode = new SMLib.Automata.IA.InterfaceAutomaton.IA_State(m.Size);
                    statesName.Add(tr.Destination);

                    m.AddState(dstNode);
                }

                t.SetDestination(dstNode);
                srcNode.Transitions.Add(t);
            }
            return m;
        }

        #region IInterOpProvider<IA_State,IA_Step> Members

        public Base.IDiGraph<InterfaceAutomaton.IA_State, InterfaceAutomaton.IA_Step> Import(string inputStr)
        {
            return ReadFromDot(inputStr);
        }

        public string Export(Base.IDiGraph<InterfaceAutomaton.IA_State, InterfaceAutomaton.IA_Step> graph)
        {
            throw new NotImplementedException();
        }

        public string Description()
        {
            return "IA <-> DOT";
        }
        #endregion
    }
}
